<?php

namespace App\Http\Controllers\QH_Api;

use App\Events\UserCourseChangeEvent;
use App\Http\Controllers\TK_Api\ApiBaseController;
use App\Models\CourseColumn;
use App\Models\LearnVideo;
use App\Models\NetCourseCdkey;
use App\Models\Qh_Cdkey;
use App\Models\Qh_Course;
use App\Models\Qh_MiniProgramComponent;
use App\Models\Qh_QuestionLibrary;
use App\Service\Redis\RedisBaseService;
use Auth;
use Carbon\Carbon;
use DB;
use Exception;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Log;
use Throwable;

class QuestionLibraryController extends ApiBaseController
{


    /**
     * 获取题库详情
     * @param $id
     * @return JsonResponse|object
     */
    public function show($id) {
        $questionLibrary = Qh_QuestionLibrary::findOrFail($id);
        $questionLibrary->course = Qh_Course::where('qlId', $questionLibrary->id)->get();
        $questionLibrary->noteCount = 0;
        $questionLibrary->wrongQuestionCount = 0;

        if (Auth::guard('api')->check()) {
            $user = Auth::guard('api')->user();
            $questionLibrary->noteCount = DB::table('notes')->where('userId', $user->id)->count();
            // 错题数量：只查当前题库
            $questionLibrary->wrongQuestionCount = DB::table('qh_user_question_logs')->where('qlId', $questionLibrary->id)->where('userId', $user->id)->where('result', 2)->count();
        }

        // 组件处理
        if (!is_null($questionLibrary->components)) {
            $componentsJson = json_decode($questionLibrary->components);
            $components = [];
            $componentsSorts = array();
            foreach ($componentsJson as $key => $row) {
                $componentsSorts[$key] = $row->sort;
            }
            array_multisort($componentsSorts, SORT_ASC, $componentsJson);

            foreach ($componentsJson as $component) {
                $c = Qh_MiniProgramComponent::find($component->id);
                if (!$c) continue;
                $c->data = qhMiniProgramComponentDataFormat($c);
                $components[] = $c;
            }
        }else {
            $components = [];
        }

        $questionLibrary->components = $components;

        return $this->restful($questionLibrary);
    }

    /**
     * 获取用户拥有的题库列表
     * @return JsonResponse|object
     * @throws \RedisException
     */
    public function getMyQuestionLibrary() {
        if (!empty(request('v2'))) {
            $courseIds = DB::table('qh_user_learn')->where('userId', $this->user->id)->distinct()->pluck('courseId')->toArray();

            // 需要分类
            $list['buy'] = DB::table('qh_user_has_course')
                ->select([
                    'qh_courses.name',
                    'qh_courses.qlId',
                    'qh_courses.id',
                    'qh_courses.questionCount',
                    'qh_user_has_course.type',
                    'qh_user_has_course.sourceId',
                ])
                ->where('qh_user_has_course.userId', $this->user->id)
                ->join('qh_courses', 'qh_user_has_course.courseId', '=', 'qh_courses.id')
                ->groupBy('qh_courses.id')
                ->get();

            foreach ($list['buy'] as $item) {
                $item->buyLog = [
                    'sourceId' => $item->sourceId,
                    'type' => $item->type,
                ];
                $item->userLearnQuestionCount = (new RedisBaseService())->getUserLearnQuestionCountByCourse($this->user->id, $item->id);
            }

            $list['free'] = Qh_Course::whereIn('id', $courseIds)
                ->select([
                    'qh_courses.name',
                    'qh_courses.qlId',
                    'qh_courses.id',
                    'qh_courses.questionCount',
                ])
                ->whereNotIn('id', function ($query) {
                    $query->select('courseId')
                        ->from('qh_user_has_course')
                        ->where('userId', $this->user->id);
                })
                ->get();
        }else {
            $courseIds = DB::table('qh_user_has_course')->where('userId', $this->user->id)->pluck('courseId')->toArray();

            $list = Qh_Course::whereIn('id', $courseIds)->get();
        }


        return $this->restful($list);

    }

    /**
     * 激活题库
     * @return JsonResponse|object
     * @throws Exception|Throwable
     */
    public function useCdkey() {
        $params = request()->validate([
            'courseId' => 'bail|required|numeric',
            'code' => 'bail|required|string'
        ], request()->all());

        $course = Qh_Course::find($params['courseId']);
        if (!$course) throw new Exception('题库不存在');

        $cdkey = Qh_Cdkey::where('code', $params['code'])->first();
        if (!$cdkey) throw new Exception('激活码不存在');
        if ($cdkey->status == 2) throw new Exception('激活码已使用');
        if ($cdkey->status == 4) throw new Exception('激活码被冻结');
        if ($cdkey->expires && Carbon::make($cdkey->expires)->lt(now())) throw new Exception('激活码已过期');
        if ($cdkey->status != 1 || ($cdkey->courseId != $params['courseId'] && $cdkey->courseId != null)) throw new Exception('激活码无效');
        // if ($cdkey->userId != null && $cdkey->userId != $this->user->id) throw new Exception('激活码无效');

        // 检查用户是否拥有了该题库
        $has = (bool)DB::table('qh_user_has_course')->where('userId', $this->user->id)->where('courseId', $course->id)->first();
        if ($has) throw new Exception('已激活该题库');

        // 开始激活
        DB::transaction(function () use ($cdkey, $course) {
            $cdkey->userId = $this->user->id;
            $cdkey->activeCourseId = $course->id;
            $cdkey->status = 2;
            $cdkey->useAt = Carbon::now();
            $cdkey->save();

            $has = DB::table('qh_user_has_course')->insert([
                'userId' => $this->user->id,
                'sourceId' => $cdkey->id,
                'courseId' => $course->id,
                'type' => 2,
                'created_at' => Carbon::now()
            ]);
            // 更新用户拥有的学科缓存
            UserCourseChangeEvent::dispatch($this->user->id);

            if (!$has) throw new Exception('激活失败');
        });

        return $this->restful();
    }

    /**
     * 使用激活码-网课
     * @return JsonResponse|object
     * @throws Throwable
     */
    public function useCdkey2() {
        $params = request()->validate([
            'dataId' => 'bail|required|int',
            'type' => 'bail|required|int|in:3,4',
            'code' => 'bail|required|string'
        ], request()->all());

        if ($params['type'] == 3) {
            $model = LearnVideo::find($params['dataId']);
        }else {
            $model = CourseColumn::find($params['dataId']);
        }

        if (!$model) throw new Exception('资源不存在');

        $cdkey = NetCourseCdkey::where('code', $params['code'])->first();
        if (!$cdkey) throw new Exception('激活码不存在');
        if ($cdkey->status == 2) throw new Exception('激活码已使用');
        if ($cdkey->status == 4) throw new Exception('激活码被冻结');
        if ($cdkey->expires && Carbon::make($cdkey->expires)->lt(now())) throw new Exception('激活码已过期');
        if ($cdkey->status != 1 || ($cdkey->dataId != $params['dataId'] && $cdkey->dataId != null)) throw new Exception('激活码无效');
        // if ($cdkey->userId != null && $cdkey->userId != $this->user->id) throw new Exception('激活码无效');
        if ($params['type'] == 3) {
            if ($cdkey->type != 1) throw new Exception('激活码无效');
        }elseif ($params['type'] == 4) {
            if ($cdkey->type != 2) throw new Exception('激活码无效');
        }

        // 检查用户是否拥有了该资源
        if ($params['type'] == 3) {
            $has = (bool)DB::table('user_learn_video_logs')
                ->where('userId', $this->user->id)
                ->where('learnVideoId', $model->id)
                ->where('isTry', 0)
                ->where('expireAt', '>', now())
                ->first();
        }elseif ($params['type'] == 4) {
            $has = (bool)DB::table('user_course_column_buy_logs')->where('userId', $this->user->id)->where('dataId', $model->id)->first();
        }
        if ($has) throw new Exception('已激活该资源');

        // 开始激活
        DB::transaction(function () use ($cdkey, $model, $params) {
            $cdkey->userId = $this->user->id;
            $cdkey->activeDataId = $model->id;
            $cdkey->status = 2;
            $cdkey->useAt = Carbon::now();
            $cdkey->save();

            if ($params['type'] == 3) {
                $expireAt = getResourceEffectiveAt($cdkey) ?? Carbon::now()->addYears();
                $sendRes = sendLearnVideoToUser([$model->id], $this->user->id, $expireAt, 2, $cdkey);
                if (!$sendRes) throw new Exception('激活失败');
            }elseif ($params['type'] == 4) {
                // 计算资源过期时间
                //Log::debug('cdkey', $cdkey->toArray());
                $expireAt = getResourceEffectiveAt($cdkey) ?? getCourseColumnExpireAt($model);
                //Log::debug($expireAt->format('Y-m-d H:i:s'));
                $resource = $model->resource;
                if (!empty($resource)) {
                    // 题库
                    if (!empty($resource['courses'])) {
                        $sendRes = sendCourseToUser($resource['courses'], $this->user->id, null, 2);
                        if (!$sendRes) throw new Exception('激活失败');
                    }
                    // 文档
                    if (!empty($resource['documents'])) {
                        $sendRes = sendDocumentToUser($resource['documents'], $this->user->id, null, 2);
                        if (!$sendRes) throw new Exception('激活失败');
                    }
                    // 视频课程
                    if (!empty($resource['learn_videos'])) {
                        $sendRes = sendLearnVideoToUser($resource['learn_videos'], $this->user->id, $expireAt, 5, $cdkey);
                        if (!$sendRes) throw new Exception('激活失败');
                    }

                    DB::table('user_course_column_buy_logs')->updateOrInsert([
                        'userId' => $this->user->id,
                        'dataId' => $model->id,
                    ], [
                        'getType' => 2,
                        'expireAt' => $expireAt,
                        'created_at' => now(),
                        'updated_at' => now()
                    ]);
                }
            }
        });

        return $this->restful();
    }
}
